package de.codecrafters.tableview.toolkit;

import de.codecrafters.tableview.providers.TableDataRowBackgroundProvider;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;


/**
 * A collection of predefined {@link TableDataRowBackgroundProvider}s.
 *
 * @author ISchwarz
 */
public final class TableDataRowBackgroundProviders {

    private TableDataRowBackgroundProviders() {
        // no instance
    }

    /**
     * Gives an implementation of {@link TableDataRowBackgroundProvider} that will return alternately the two
     * given colors.
     *
     * @param colorEvenRows The color that will be returned for rows with an even index.
     * @param colorOddRows  The color that will be returned for rows with an odd index.
     * @return A {@link TableDataRowBackgroundProvider} with the described behaviour.
     */
    public static TableDataRowBackgroundProvider<Object> alternatingRowColors(final int colorEvenRows, final int colorOddRows) {
        return new AlternatingTableDataRowColorProvider(colorEvenRows, colorOddRows);
    }

    /**
     * Gives an implementation of {@link TableDataRowBackgroundProvider} that will return alternately the two
     * given colors.
     *
     * @param drawableEvenRows The {@link ohos.agp.components.element.Element} that will be returned for rows with an even index.
     * @param drawableOddRows  The {@link Element}  that will be returned for rows with an odd index.
     * @return A {@link TableDataRowBackgroundProvider} with the described behaviour.
     */
    public static TableDataRowBackgroundProvider<Object> alternatingRowDrawables(final Element drawableEvenRows, final Element drawableOddRows) {
        return new AlternatingTableDataRowDrawableProvider(drawableEvenRows, drawableOddRows);
    }

    /**
     * Gives an implementation of {@link TableDataRowBackgroundProvider} that will return the given color for each row.
     *
     * @param color The color that will be used for each row.
     * @return A {@link TableDataRowBackgroundProvider} with the described behaviour.
     */
    public static TableDataRowBackgroundProvider<Object> similarRowColor(final int color) {
        return new SimpleTableDataRowColorProvider(color);
    }

    /**
     * Gives an implementation of {@link TableDataRowBackgroundProvider} that will return the given color for each row.
     *
     * @param drawable The {@link Element} that will be used for each row.
     * @return A {@link TableDataRowBackgroundProvider} with the described behaviour.
     */
    public static TableDataRowBackgroundProvider<Object> similarRowDrawable(final Element drawable) {
        return new SimpleTableDataRowDrawableProvider(drawable);
    }

    /**
     * An implementation of {@link TableDataRowBackgroundProvider} that will return a {@link Element} for the
     * given color for every row.
     *
     * @author ISchwarz
     */
    private static class SimpleTableDataRowColorProvider implements TableDataRowBackgroundProvider<Object> {

        private final ShapeElement colorDrawable;

        public SimpleTableDataRowColorProvider(final int color) {
            ShapeElement se = new ShapeElement();
            se.setRgbColor(new RgbColor(color));
            this.colorDrawable = se;
        }

        /**
         * getRowBackground
         * get color from row.
         *
         * @param rowIndex rowIndex
         * @param rowData  rowData
         * @return color element
         */
        public Element getRowBackground(final int rowIndex, final Object rowData) {
            return colorDrawable;
        }
    }

    /**
     * An implementation of {@link TableDataRowBackgroundProvider} that will return a {@link Element} for the
     * given color for every row.
     *
     * @author ISchwarz
     */
    private static class SimpleTableDataRowDrawableProvider implements TableDataRowBackgroundProvider<Object> {

        private final Element drawable;

        public SimpleTableDataRowDrawableProvider(final Element drawable) {
            this.drawable = drawable;
        }

        @Override
        public Element getRowBackground(final int rowIndex, final Object rowData) {
            return drawable;
        }
    }

    /**
     * An implementation of {@link TableDataRowBackgroundProvider} that will return alternately the two
     * given colors as {@link Element}.
     *
     * @author ISchwarz
     */
    private static class AlternatingTableDataRowColorProvider implements TableDataRowBackgroundProvider<Object> {

        private final Element colorDrawableEven;
        private final Element colorDrawableOdd;

        public AlternatingTableDataRowColorProvider(final int colorEven, final int colorOdd) {

            ShapeElement oddSE = new ShapeElement();
            oddSE.setRgbColor(RgbColor.fromArgbInt(colorOdd));
            ShapeElement evenSE = new ShapeElement();
            evenSE.setRgbColor(RgbColor.fromArgbInt(colorEven));
            this.colorDrawableEven = evenSE;
            this.colorDrawableOdd = oddSE;
        }

        @Override
        public Element getRowBackground(final int rowIndex, final Object rowData) {
            if (rowIndex % 2 == 0) {
                return colorDrawableEven;
            }
            return colorDrawableOdd;
        }
    }

    /**
     * An implementation of {@link TableDataRowBackgroundProvider} that will return alternately the two
     * given colors as {@link Element}.
     *
     * @author ISchwarz
     */
    private static class AlternatingTableDataRowDrawableProvider implements TableDataRowBackgroundProvider<Object> {

        private final Element drawableEven;
        private final Element drawableOdd;

        public AlternatingTableDataRowDrawableProvider(final Element drawableEven, final Element drawableOdd) {
            this.drawableEven = drawableEven;
            this.drawableOdd = drawableOdd;
        }

        @Override
        public Element getRowBackground(final int rowIndex, final Object rowData) {
            if (rowIndex % 2 == 0) {
                return drawableEven;
            }
            return drawableOdd;
        }
    }

}
